/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.generatecomponent;


import com.inspur.edp.bef.bemanager.codegenerator.JavaCompCodeNames;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.component.base.GspComponent;
import com.inspur.edp.bef.component.json.ComponentConstantElement;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.api.entity.MetadataReference;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.ArrayList;

/**
 * 元数据交互工具服务类
 *
 * @author hanll02
 */
public class GspMetadataExchangeUtil {

  public static GspMetadataExchangeUtil getInstance() {
    return new GspMetadataExchangeUtil();
  }

  private GspMetadataExchangeUtil() {
  }

  /**
   * 业务实体编号
   *
   */
  private String privateBizEntityCode;

  private String getBizEntityCode() {
    return privateBizEntityCode;
  }

  private void setBizEntityCode(String value) {
    privateBizEntityCode = value;
  }

  /**
   * 元数据存放路径
   *
   */
  private String privateMetadataPath;

  private String getMetadataPath() {
    return privateMetadataPath;
  }

  private void setMetadataPath(String value) {
    privateMetadataPath = value;
  }

  /**
   * 元数据名称
   *
   */
  private String privateComponentName;

  private String getComponentName() {
    return privateComponentName;
  }

  private void setComponentName(String value) {
    privateComponentName = value;
  }

  /**
   * 是否是新建元数据
   *
   */
  private boolean privateIsNewMetadata;

  private boolean getIsNewMetadata() {
    return privateIsNewMetadata;
  }

  private void setIsNewMetadata(boolean value) {
    privateIsNewMetadata = value;
  }

  private String privateBizObjectID;

  private String getBizObjectID() {
    return privateBizObjectID;
  }

  private void setBizObjectID(String value) {
    privateBizObjectID = value;
  }

  private String privateNameSpace;

  private String getNameSpace() {
    return privateNameSpace;
  }

  private void setNameSpace(String value) {
    privateNameSpace = value;
  }

  /**
   * 创建构件元数据，返回构件元数据ID
   *
   * @param component     构件实体
   * @param path          生成构件元数据的路径
   * @param bizEntityCode 业务实体编号
   * @return 生成的构件元数据名称
   * <see cref="string"/>
   */
  public final GspMetadata establishGspMetdadata(GspComponent component, String path,
      String bizEntityCode, String bizObjectID, String nameSpace) {
    this.setIsNewMetadata(true);
    this.setBizEntityCode(bizEntityCode);
    this.setMetadataPath(path);
    this.setBizObjectID(bizObjectID);
    this.setNameSpace(nameSpace);
    GspMetadata metadata = BuildGspMetadataEntity(component);
    return GenerateGspMetadata(metadata);
  }

  /**
   * 更新构件元数据
   *
   * @param component 构件实体
   * @param fullPath  要修改的构件元数据完整路径
   */
  public final void UpdateGspMetadata(GspComponent component, String fullPath, String bizEntityCode,
      String bizObjectID, String nameSpace) {
    this.setIsNewMetadata(false);
    this.setBizEntityCode(bizEntityCode);
    this.setBizObjectID(bizObjectID);
    FileService fileService = SpringBeanUtils.getBean(FileService.class);

    this.setMetadataPath(fileService.getDirectoryName(fullPath));
    this.setNameSpace(nameSpace);
    this.setComponentName(fileService.getFileNameWithoutExtension(fullPath));
    GspMetadata metadata = BuildGspMetadataEntity(component);
    UpdateComponentMetadata(metadata, fullPath);
  }


  /**
   * 创建GspMetadata实体
   *
   * @param component 构件实体
   * @return GspMetadata实体
   */
  private GspMetadata BuildGspMetadataEntity(GspComponent component) {
    GspMetadata metadata = CreateMetadataEntity();

    EvaluateMetadataHeader(component, metadata);
    EvaluateMetadataContent(component, metadata);
    return metadata;
  }

  /**
   * 创建元数据实例
   *
   * @return 实例化的元数据
   * <see cref="GspMetadata"/>
   */
  private GspMetadata CreateMetadataEntity() {
    GspMetadata tempVar = new GspMetadata();
    tempVar.setHeader(new MetadataHeader());
    tempVar.setRefs(new ArrayList<MetadataReference>());
    GspMetadata metadata = tempVar;
    return metadata;
  }

  /**
   * 为元数据的Header属性赋值
   *
   * @param component 构件实体
   * @param metadata  元数据实体
   */
  private void EvaluateMetadataHeader(GspComponent component, GspMetadata metadata) {
    if (CheckInfoUtil.checkNull(metadata.getHeader().getNameSpace())) {
      metadata.getHeader().setNameSpace(getNameSpace());
    }

    metadata.getHeader().setName(generateComponentMetadataName(component, this.getMetadataPath()));
    metadata.getHeader().setCode(generateComponentMetadataName(component, this.getMetadataPath()));
    metadata.getHeader().setFileName(
        this.getComponentName() + getCmpMetadataExtendNameByCompType(component.getComponentType()));
    metadata.getHeader().setType(getCmpMetadataTypeByCompType(component.getComponentType()));

    if (!CheckInfoUtil.checkNull(getBizObjectID())) {
      metadata.getHeader().setBizobjectID(getBizObjectID());
    }

    if (CheckInfoUtil.checkNull(metadata.getHeader().getId()) && CheckInfoUtil
        .checkNull(component.getComponentID()))
    {
      MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
      metadata = metadataService.initializeMetadataEntity(metadata);
      component.setComponentID(metadata.getHeader().getId());
    } else if (CheckInfoUtil.checkNull(metadata.getHeader().getId()) && !CheckInfoUtil
        .checkNull(component.getComponentID()))
    {
      metadata.getHeader().setId(component.getComponentID());
    }
  }

  /**
   * 为元数据的Content属性赋值
   *
   * @param component 构件实体
   * @param metadata  元数据实体
   */
  private void EvaluateMetadataContent(GspComponent component, GspMetadata metadata) {
    metadata.setContent(component);
  }


  /**
   * 获取构件元数据拼接后缀名
   *
   * @param componentType 构件类型
   * @return
   */
  private String GetCmpMetadataExtendSuffixByCompType(String componentType) {
    if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
      return JavaCompCodeNames.ActionMgrControllerName;
    }
    else if (componentType.equals(ComponentConstantElement.BEComponent)) {
      return JavaCompCodeNames.ActionControllerName;
    }
    else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
      return JavaCompCodeNames.DeterminationControllerName;
    }
    else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
      return JavaCompCodeNames.ValidationControllerName;
    } else {
      throw new RuntimeException("未知构件类型");
    }
  }

  /**
   * 获取构件元数据扩展名
   *
   * @param componentType 构件类型
   * @return
   */
  private String getCmpMetadataExtendNameByCompType(String componentType) {

    if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
      return JavaCompCodeNames.BEMgrCmpExtendName;
    }
    else if (componentType.equals(ComponentConstantElement.BEComponent)) {
      return JavaCompCodeNames.BECmpExtendName;
    }
    else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
      return JavaCompCodeNames.DtmCmpExtendName;
    }
    else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
      return JavaCompCodeNames.ValCmpExtendName;
    } else {
      throw new RuntimeException("未知构件类型");
    }
  }

  /**
   * 获取构件元数据类型
   *
   * @param componentType 构件类型
   * @return
   */
  private String getCmpMetadataTypeByCompType(String componentType) {

    if (componentType.equals(ComponentConstantElement.BEMgrComponent)) {
      return JavaCompCodeNames.BEMgrComponent;
    }
    else if (componentType.equals(ComponentConstantElement.BEComponent)) {
      return JavaCompCodeNames.BEComponent;
    }
    else if (componentType.equals(ComponentConstantElement.DeterminationComponent)) {
      return JavaCompCodeNames.DeterminationComponent;
    }
    else if (componentType.equals(ComponentConstantElement.ValidationComponent)) {
      return JavaCompCodeNames.ValidationComponent;
    } else {
      throw new RuntimeException("未知构件类型");
    }
  }


  /**
   * 生成构件元数据
   *
   * @param metadata 元数据
   * @param
   * @return 生成的构件元数据名称
   * <see cref="string"/>
   */
  private GspMetadata GenerateGspMetadata(GspMetadata metadata) {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

    metadataService.createMetadata(this.getMetadataPath(), metadata);
    return metadata;
  }

  private void UpdateComponentMetadata(GspMetadata metadata, String fullPath) {
    MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

    metadataService.saveMetadata(metadata, fullPath);
  }

  /**
   * 生成当前路径下唯一的元数据名称
   *
   * @param component 构件实体
   * @param path      生成的元数据存放路径
   * @return 唯一的要生成的元数据名称
   */
  private String generateComponentMetadataName(GspComponent component, String path) {
    String metadataFileName = this.getBizEntityCode() + component.getComponentCode()
        + GetCmpMetadataExtendSuffixByCompType(component.getComponentType());
    if (this.getIsNewMetadata()) {
      String orgMetadataFileName = metadataFileName;
      String metadataFileNameWithSuffix =
          metadataFileName + getCmpMetadataExtendNameByCompType(component.getComponentType());
      int index = 0;
      MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);

      while (metadataService.isMetadataExist(path, metadataFileNameWithSuffix)) {
        metadataFileName = orgMetadataFileName + ++index;
        metadataFileNameWithSuffix =
            metadataFileName + getCmpMetadataExtendNameByCompType(component.getComponentType());
      }
      this.setComponentName(metadataFileName);
    }

    return metadataFileName;
  }
}
